<?php
declare (strict_types = 1);

namespace app\model;

use app\exception\ModelEmptyException;
use app\exception\ModelException;
use app\exception\ModelNotUniqueException;
use app\service\CacheService;
use think\facade\Cache;
use think\Model as BaseModel;

/**
 * @mixin \think\Model
 */
class Model extends BaseModel
{
    // msg
    public $getMsg;
    public $addMsg;
    public $updateMsg;
    public $delMsg;

    // 成功编码
    public $sucCode = 0;
    // 软删除数据
    public $delData;
    // 错误编码
    public $errorCode = '50011';

    public $listCacheKey;
    public $detailCacheKey;
    public $className;


    protected $hidden = [
        'password','seller_id'
    ];

    public function __construct($data=[])
    {
        $this->delData = [
            'is_del' => 2,
            'delete_time' => time(),
            'update_time' => time(),
        ];
        $this->className = $this->getClassName();
        $this->listCacheKey = $this->className . '_cache_list';
        $this->detailCacheKey = $this->className . '_cache_detail';
        $this->getMsg = lang('获取成功');
        $this->addMsg = lang('添加成功');
        $this->updateMsg = lang('修改成功');
        $this->delMsg = lang('删除成功');
        parent::__construct($data);
    }

    /**
     * @param array $where
     * @return array
     */
    public function getCustomDataColumn($column,array $where = []):array
    {
        try{
            $res =  $this->where($where)->column($column);
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->getMsg,$res);
    }


    /**
     * @param array $where
     * @param int $limit
     * @return array
     */
    public function getCustomDataList(array $where = [],int $limit = 10, $order = 'id desc',$field="*"):array
    {
        try{
            $res =  $this->field($field)->where($where)->order($order)->paginate($limit);
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->getMsg,$res);
    }

    public function getLimitCustomData($where,$order='id desc',$limit=10,$field="*",$with=[],$offset=0): array
    {
        $key = md5($this->className . json_encode([$where,$order,$limit,$field,$with,$offset]));
        $res = Cache::get($key);
        if(!empty($res)){
            return dataReturn($this->sucCode,$this->getMsg,json_decode($res,true));
        }
        try{
            $res =  $this->field($field)->with($with)->where($where)->order($order)->limit($offset,$limit)->select()->toArray();
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        Cache::set($key,json_encode($res));
        CacheService::append($this->listCacheKey,$key);
        return dataReturn($this->sucCode,$this->getMsg,$res);
    }

    public function getAllCustomArrayData($where,$order='id desc',$field="*",$with=[],$offset=0): array
    {

        $key = md5($this->className . json_encode([$where,$order,$field,$with]));
        $res = Cache::get($key);
        if(!empty($res)){
            return dataReturn($this->sucCode,$this->getMsg,json_decode($res,true));
        }
        try{

            $res = [];
            if($offset<=0){
                $res = $this->field($field)->with($with)->where($where)->order($order)->select()->toArray();
            }else{
                $count = $this->field($field)->with($with)->where($where)->count();
                $last = (int)bcsub((string)$count,(string)$offset);
                if($last>0){
                    $res = $this->field($field)->with($with)->where($where)->order($order)->limit($offset,$last)->select()->toArray();
                }
            }

        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        Cache::set($key,json_encode($res));
        CacheService::append($this->listCacheKey,$key);
        return dataReturn($this->sucCode,$this->getMsg,$res);
    }

    public function getAllCustomDataModel($where,$order='id desc',$field="*",$with=[]): array
    {
        try{
            $res =  $this->field($field)->with($with)->where($where)->order($order)->select();
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->getMsg,$res);
    }

    /**
     * @param array $name
     * @return array
     */
    public function getCustomData(array $name = [],$with=[],$field="*"): array
    {
        try{
            $res =  $this->with($with)->field($field)->where($name)->find();
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->getMsg,$res);

    }

    /**
     * @param array $where
     * @return array with
     * @throws ModelEmptyException
     * @throws ModelException
     */
    public function getCustomArrayData(array $where = [],$with=[],string $field='*'): array
    {
        $key = md5($this->className .  json_encode([$where,$field,$with]));
        $res = Cache::get($key);
        if(!empty($res)){
            return dataReturn($this->sucCode,$this->getMsg,json_decode($res,true));
        }
        try{
            $res =  $this->field($field)->with($with)->where($where)->findOrEmpty()->toArray();
            if(empty($res)){
                throw new ModelEmptyException();
            }
        }catch(ModelEmptyException $me){
            throw new ModelEmptyException();
        }catch(\Exception $e){
            throw new ModelException($e->getMessage());
        }
        Cache::set($key,json_encode($res));
        CacheService::append($this->listCacheKey,$key);
        return dataReturn($this->sucCode,$this->getMsg,$res);

    }

    /**
     * @param $param
     * @return array
     */
    public function addCustomData($param): array
    {
        try{
            $res =  self::create($param);
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->addMsg,$res);
    }

    /**
     * @param $param
     * @return array
     */
    public function addAllCustomData($param): array
    {
        try{
            $res =  self::saveAll($param);
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->addMsg,$res);
    }

    /**
     * @param array $where
     * @param $param
     * @return array
     */
    public function updateCustomData(array $where, $param,$strict = true): array
    {
        try{
            $res =  self::strict($strict)->where($where)->update($param);
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->updateMsg,$res);
    }

    /**
     * @param $where
     * @return array
     */
    public function delCustomData($where): array
    {
        try{
            $res =  self::where($where)->delete();
        }catch(\Exception $e){
            return dataReturn($this->errorCode,$e->getMessage());
        }
        return dataReturn($this->sucCode,$this->delMsg,$res);
    }
    /**
     * @throws ModelNotUniqueException
     * @throws ModelException
     */
    public function saveUnique($where, $msg = '')
    {
        try{
            $res = $this->where($where)->find();
        }catch(\Exception $e){
            throw new ModelException($e->getMessage());
        }
        if(!empty($res)){
            throw new ModelNotUniqueException(!empty($msg)?$msg:lang('内容已存在'));
        }
    }

    /**
     * @throws ModelException
     * @throws ModelNotUniqueException
     */
    public function updateUnique($where, $id, $msg = '')
    {
        try{
            $res = $this->where($where)->find();
        }catch(\Exception $e){
            throw new ModelException($e->getMessage());
        }
        if(!empty($res) && $res['id'] != $id){
            throw new ModelNotUniqueException(!empty($msg)?$msg:lang('内容已存在'));
        }
    }

    public function getClassName(): string
    {
        $reflection = new \ReflectionClass($this);
        return $reflection -> getShortName();
    }
}
